home *** CD-ROM | disk | FTP | other *** search
- /*
- * Routines for sampling from a Soundblaster-16 sound card.
- * These routines require the functions in sbio.c derived from
- * Ethan Brodsky's Soundblaster-16 programming library .
- * Copyright (C) 1997 Philip VanBaren & Emil Laurentiu
- * Last modified: Wednesday, 06 August 1997
- */
-
- #include "freq.h"
-
- #ifdef SC_SB16
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <mem.h>
- #include <graphics.h>
- #include "sb.h"
- #include "sbio.h"
- #include "extern.h"
-
- /* Function prototypes */
- int atox16( char *ptr );
- void interrupt sb16_callback( void );
- void init_sb16( char **environ );
- void reset_sb16( void );
- void halt_sb16( void );
- void cleanup_sb16( void );
- void recordblock_sb16( void far * buffer );
- void set_mixer_sb16( int mix, int level );
-
- int
- atox16( char *ptr )
- {
- // Convert ascii hex values to integer
- int v = 0;
-
- while ( ( ( *ptr >= '0' ) && ( *ptr <= '9' ) ) || ( ( ( *ptr | 0x20 ) >= 'a' ) && ( ( *ptr | 0x20 ) <= 'f' ) ) )
- {
- v = v * 16;
- if ( *ptr <= '9' )
- v = v + *ptr - '0';
- else
- v = v + ( *ptr | 0x20 ) - 'a' + 10;
- ptr++;
- }
- return v;
- }
-
- #define is_blaster(var) ((((var)[0]=='B')||((var)[0]=='b')) && \
- (((var)[1]=='L')||((var)[1]=='l')) && \
- (((var)[2]=='A')||((var)[2]=='a')) && \
- (((var)[3]=='S')||((var)[3]=='s')) && \
- (((var)[4]=='T')||((var)[4]=='t')) && \
- (((var)[5]=='E')||((var)[5]=='e')) && \
- (((var)[6]=='R')||((var)[6]=='r')))
-
- /* Turn off stack checking for this routine */
- #pragma option -N-
- void interrupt
- sb16_callback( )
- {
- extern int poll16port, dma_maskport, dma_stopmask;
- unsigned int far *s, far * d;
- int i;
-
- /*
- * Callback function. This function is called every time a buffer has been
- * filled. It copies the latest data, and sets a flag so the main loop
- * recognises and processes the buffer.
- */
- d = buffer[record_buffer];
- s = dmaptr + (curblock * fftlen);
- for ( i = 0; i < fftlen; i++ )
- *d++ = *s++;
- flag[record_buffer] = 1;
- if ( ++record_buffer >= BUFFERS )
- record_buffer = 0;
-
- curblock = !curblock; /* Toggle active block flag */
- /* If we hit the end of the queued buffers, stop recording */
- if ( record_buffer == queue_buffer )
- {
- write_dsp( 0xD5 ); /* Stop digitized sound xfer */
- outportb( dma_maskport, dma_stopmask ); /* Mask DMA channel */
- sb16dmarunning = 0;
- }
- /* Acknowledge the interrupt */
- inportb( poll16port );
- outportb( 0x20, 0x20 );
- outportb( 0xA0, 0x20 );
- }
-
- /* Restore stack checking to the command-line specified state */
- #pragma option -N.
-
-
- void
- init_sb16( char **environ )
- {
- int i;
- // Scan the environment variables for BLASTER=Axxx Ix Dx
- for ( i = 0; environ[i] != NULL; i++ )
- {
- if ( is_blaster( environ[i] ) )
- {
- int j;
- DOUT( "SB16: Found the BLASTER environment variable:" );
- DOUT( environ[i] );
- for ( j = 8; environ[i][j] != 0; j++ )
- {
- if ( ( environ[i][j] == 'A' ) || ( environ[i][j] == 'a' ) )
- {
- DOUT( "SB16: Axxx found" );
- sb_addr = atox16( &environ[i][j + 1] );
- }
- if ( ( environ[i][j] == 'H' ) || ( environ[i][j] == 'h' ) )
- {
- DOUT( "SB16: Hx found" );
- sb_dma = atoi( &environ[i][j + 1] );
- }
- if ( ( environ[i][j] == 'I' ) || ( environ[i][j] == 'i' ) )
- {
- DOUT( "SB16: Ix found" );
- sb_irq = atoi( &environ[i][j + 1] );
- }
- // Skip to the next parameter
- while ( ( environ[i][j] != ' ' ) && ( environ[i][j + 1] != 0 ) )
- j++;
- }
- break;
- }
- }
- #ifdef DEBUG_OUTPUT
- {
- char message[100];
- sprintf( message, "SB16: Address=0x%03x, DMA=%d, IRQ=%d", sb_addr, sb_dma, sb_irq );
- DOUT( message );
- }
- #endif
- /* Set up the pointers to the recording routines */
- reset_soundcard = reset_sb16;
- halt_soundcard = halt_sb16;
- cleanup_soundcard = cleanup_sb16;
- recordblock = recordblock_sb16;
- set_mixer = set_mixer_sb16;
- sample_size = 16;
- mixers = 1;
-
- DOUT( "SB16: Initializing the card" );
-
- if ( !init_sb( sb_addr, sb_irq, sb_dma, input, MAX_LEN ) )
- {
- closegraph( );
- puts( "Unable to initialize the Soundblaster16 card, aborting..." );
- exit( 1 );
- }
- DOUT( "SB16: Reading initial mixer settings" );
- mic_level = get_mic_level( );
- ext_level = get_line_level( );
- int_level = get_cd_level( );
- DOUT( "SB16: Set Master volume & FM volume to maximum" );
- set_master_level( 0x0f );
- set_fm_level( 0x0f );
- }
-
- void
- reset_sb16( void )
- {
- int i;
- /* Round sampling rate to a valid value for the SB card */
- i = floor( 1000000.0 / SampleRate + 0.5 );
- if ( i < 1 )
- i = 1;
- SampleRate = floor( 1000000.0 / ( double ) i + 0.5 );
-
- /* Reset the buffer pointers */
- queue_buffer = 0; // Pointer to next buffer to be queued
- record_buffer = 0; // Pointer to next buffer to be filled
- process_buffer = 0; // Pointer to next buffer to be FFTed
-
- for ( i = 0; i < BUFFERS; i++ )
- flag[i] = 0;
-
- /* This function starts the DMA process. */
- DOUT( "SB16: Starting the recording process" );
- recordblock_sb16( ( char far * ) buffer[queue_buffer] );
- }
-
- void
- halt_sb16( void )
- {
- /*
- * Shut down the DMA system.
- */
- DOUT( "SB16: Stopping the sampling process" );
- stopio( );
- }
-
- void
- cleanup_sb16( void )
- {
- /*
- * Shut down the DMA system and remove the interrupt handler.
- */
- DOUT( "SB16: Stopping the sampling process and cleaning up" );
- shutdown_sb( );
- Sb_FM_Reset( );
- }
-
- void
- recordblock_sb16( void far * buffer )
- {
- /* Start transferring data into the DMA buffer */
- if ( ++queue_buffer >= BUFFERS )
- queue_buffer = 0;
- /* If the DMA has halted, restart it */
- if ( !sb16dmarunning )
- startio( ( unsigned int ) SampleRate, fftlen );
- }
-
- void
- set_mixer_sb16( int mix, int level )
- {
- /*
- * Set a mixer level on the PAS16 card
- */
- if ( mix == MIXER_EXT )
- {
- DOUT( "SB16: Setting the line mixer level" );
- set_line_level( level );
- }
- else if ( mix == MIXER_INT )
- {
- DOUT( "SB16: Setting the CD mixer level" );
- set_cd_level( level );
- }
- else if ( mix == MIXER_MIC )
- {
- DOUT( "SB16: Setting the microphone mixer level" );
- set_mic_level( level );
- }
- }
-
- #endif
-